home *** CD-ROM | disk | FTP | other *** search
/ United Public Domain Gold 2 / United Public Domain Gold 2.iso / utilities / pu087.dms / pu087.adf / fortune / fortune.c < prev    next >
C/C++ Source or Header  |  1990-12-05  |  11KB  |  391 lines

  1. /*  (c) 1990 S.Hawtin.
  2.   Permission is granted to copy this file provided
  3.    1) It is not used for commercial gain
  4.    2) This notice is included in all copies
  5.    3) Altered copies are marked as such
  6.  
  7.   No liability is accepted for the contents of the file.
  8.  
  9. */
  10.  
  11. /**********************************************************************/
  12.  
  13. /* 
  14.   This is a short example program that selects a phrase from a file and
  15. prints it.
  16. */
  17.  
  18. /* We are going to print stuff to files so we must have "stdio.h" */
  19. #include <stdio.h>
  20.  
  21. /* Comment out this line to remove the speech bit */
  22. #define SPEAKING 1
  23.  
  24. #ifdef SPEAKING
  25. /* The include files for the narrator device */
  26. #include <exec/ports.h>
  27. #include <devices/narrator.h>
  28. #endif
  29.  
  30. /**********************************************************************/
  31.  
  32. /* First a set of constants */
  33.  
  34. /* 
  35.   The data file that all the phrases come from.
  36. This file must be at least MIN_LENGTH characters long, and have 
  37. more than 3 phrases in.
  38. */
  39. #define MIN_LENGTH 100
  40. #define SRC_FILE "fortune.txt"
  41.  
  42. /* 
  43.   Some special "characters", to indicate conditions other than 
  44. normal characters read in from the file. 
  45. */
  46. #define MY_EOF  -1
  47. #define MY_EOL  -2
  48.  
  49. /* Some variables to control the program */
  50.  
  51. /* A flag to tell us to be noisy so that we can see what is going on */
  52. static int noisy = 0;
  53.  
  54. /* A flag to tell us not to use the narrator */
  55. static int silent = 0;
  56.  
  57. /**********************************************************************/
  58.  
  59. /* Some special NorthC things */
  60.  
  61. #ifdef NORTHC
  62.  
  63. /* This will be 0 if program was called from CLI */
  64. extern long _fromWB;
  65.  
  66. /* 
  67.   The description of a console window to use if called from the 
  68. workbench
  69. */ 
  70. char *_WBConsole="con:20/40/600/70/NorthC: Fortune Program";
  71.  
  72. #endif
  73.  
  74. /**********************************************************************/
  75.  
  76. /* The functions */
  77.  
  78. static int
  79. tyi(fptr)
  80.     FILE *fptr;
  81.    {/* 
  82.       Input a single character from the file, if we find the end of 
  83.     a phrase return MY_EOL, if we find the end of a file return MY_EOF.
  84.     */
  85.  
  86.     /* Somewhere to keep the characters as they are read */
  87.     int next;
  88.  
  89.     /* First get the next character from the file */
  90.     next = fgetc(fptr);
  91.  
  92.     /* 
  93.       Now we have three special cases,
  94.          1) the '\' charcter:  Read the next character without 
  95.             translating it.  This lets us embed newlines in a phrase.
  96.          2) the newline charcter:  Tell the caller we have got the
  97.             end of the phrase.
  98.          3) the end of file:  Tell the caller we have an end of file.
  99.     */
  100.     if(next=='\\')
  101.        {next = fgetc(fptr);
  102.         /* Translate some escape characters */
  103.         if(next=='n')
  104.             next = '\n';
  105.           else if(next=='b')
  106.             next = '\b';
  107.         }
  108.       else if(next=='\n')
  109.         next = MY_EOL;
  110.       else if (next==EOF || feof(fptr))
  111.         next = MY_EOF;
  112.     return(next);
  113.     }
  114.  
  115. #ifdef SPEAKING
  116. /* We are going to output the phrase through the narrator device */
  117.  
  118. /* The audio channels we are going to use, these are from the 
  119.    Amiga ROM Kernel Reference Manual: Libraries and Devices
  120.    I have no idea what they do */
  121. static BYTE audChanMasks[4] = {3,5,10,12};
  122.  
  123. static void
  124. say(some_lines)
  125.     char *some_lines[];
  126.    {/* Use the speech device to output some lines of text */
  127.  
  128.     /* A function that returns a structure */
  129.     extern struct MsgPort *CreatePort();
  130.     extern void *OpenLibrary();
  131.  
  132.     /* Internal variables for the function */
  133.     void *trans_lib;
  134.     int count,retCount;
  135.     char buffer[256];
  136.     struct MsgPort *writeport = NULL;
  137.     struct narrator_rb *writeNarrator = NULL;
  138.  
  139.     if(noisy)
  140.         printf("\n");
  141.  
  142.     /* First open the translator library to translate the phrases */
  143.     trans_lib = OpenLibrary("translator.library",0L);
  144.     if(NULL==trans_lib)
  145.        {
  146.         if(noisy)
  147.             printf("Cannot open translator library\n");
  148.         return;
  149.         }
  150.  
  151.     /* Now set up the structures to communicate with the narrator device */
  152.     writeport = CreatePort(0,0);
  153.     if(writeport==NULL)
  154.        {
  155.         if(noisy)
  156.             printf("Cannot open ports\n");
  157.         goto abort;
  158.         }
  159.     writeNarrator = (struct narrator_rb *)CreateExtIO(writeport,
  160.                                           sizeof(struct narrator_rb));
  161.     if(writeNarrator==NULL)
  162.        {
  163.         if(noisy)
  164.             printf("Cannot create io blocks\n");
  165.         goto abort;
  166.         }
  167.  
  168.     /* Now set up the write message structures */
  169.     writeNarrator->ch_masks = (audChanMasks);
  170.     writeNarrator->nm_masks = sizeof(audChanMasks);
  171.     writeNarrator->message.io_Data = (APTR)buffer;
  172.     writeNarrator->message.io_Length = 256;
  173.     writeNarrator->message.io_Command = CMD_WRITE;
  174.  
  175.     if(OpenDevice("narrator.device",0L,writeNarrator,0L)!=0)
  176.        {
  177.         if(noisy)
  178.             printf("Cannot open narrator\n");
  179.         goto abort;
  180.         }
  181.     
  182.     /* Now go through the lines one at a time */
  183.     for(count=0;some_lines[count];++count)
  184.        {/* Say each line */
  185.         retCount = 0;
  186.         do {
  187.             retCount = Translate(&some_lines[count][-retCount],
  188.                              retCount+strlen(some_lines[count]),buffer,256);
  189.             if(noisy)
  190.                 printf("Say \"%s\"\n",buffer);
  191.             writeNarrator->message.io_Length = strlen(buffer);
  192.             if(SendIO(writeNarrator)!=NULL)
  193.                {
  194.                 if(noisy)
  195.                     printf("Cannot do write!\n");
  196.                 goto abort;
  197.                 }
  198.             WaitIO(writeNarrator);
  199.             } while (retCount!=0);
  200.         }
  201.  
  202.     /* No need to close the library NorthC will do it for us */
  203.     CloseLibrary(trans_lib);
  204.     CloseDevice(writeNarrator);
  205. abort:
  206.     if(writeNarrator)
  207.         DeleteExtIO(writeNarrator,sizeof(struct narrator_rb));
  208.     if(writeport)
  209.         DeletePort(writeport);
  210.     }
  211. #endif
  212.  
  213. static int
  214. find_next(fptr)
  215.     FILE *fptr;
  216.    {/* 
  217.       Keep reading until we find the end of the current phrase, when 
  218.     we have the end of phrase return true if we did not get the end 
  219.     of file as well.
  220.     */
  221.     int next;
  222.  
  223.     /* Need to do two reads to make sure we have not hit a '\n'
  224.        in the middle of a multi line phrase */
  225.     next = tyi(fptr);
  226.     next = tyi(fptr);
  227.     while(next!=MY_EOL && next!=MY_EOF)
  228.         next = tyi(fptr);
  229.     return(next!=MY_EOF);
  230.     }
  231.  
  232. #define LINE_LEN 128
  233. #define MAX_LINE 10
  234.  
  235. static int
  236. out_next(fptr)
  237.     FILE *fptr;
  238.    {/* 
  239.       Output the next phrase to the terminal, this involves reading the
  240.     phrase and outputting until we run out of characters.
  241.     Again if we found the end of the file return false.
  242.     */
  243.     int next;
  244. #ifdef SPEAKING
  245.     /* If sending stuff to the narrator we must keep track of what has been 
  246.        printed so far */
  247.     char *phrase[MAX_LINE];
  248.     int  num_lines = 0;
  249.     int  curr_end;
  250.  
  251.     /* Where we build up the phrase for the speech device */
  252.     phrase[0] = malloc(LINE_LEN);
  253.     num_lines = 0;
  254.     curr_end = 0;
  255. #endif
  256.  
  257.     next = tyi(fptr);
  258.     while(next!=MY_EOL && next!=MY_EOF)
  259.        {fputc(next,stdout);
  260.  
  261. #ifdef SPEAKING
  262.         /* Put the next character into the phrase buffer */
  263.         if(phrase[num_lines])
  264.             phrase[num_lines][curr_end++] = next;
  265. #endif
  266.  
  267.         /* Put four spaces at the start of each line */
  268.         if(next=='\n')
  269.            {puts("    ");
  270. #ifdef SPEAKING
  271.             /* Add a new line on to the phrase */
  272.             phrase[num_lines++][--curr_end] = '\0';
  273.             curr_end = 0;
  274.             phrase[num_lines] = malloc(LINE_LEN);
  275. #endif
  276.             }
  277.             
  278.         /* Get the next charcter from the file */
  279.         next = tyi(fptr);
  280.         }
  281.  
  282. #ifdef SPEAKING
  283.     phrase[num_lines++][curr_end] = '\0';
  284.     phrase[num_lines] = NULL;
  285.  
  286.     /* Flush the buffer to give the user a clue while the speech is 
  287.        going on */
  288.     fflush(stdout);
  289.  
  290.     /* Go speak the phrase */
  291.     if(!silent)
  292.         say(phrase);
  293.  
  294.     /* Now free the space that we grabbed for the phrase */
  295.     for(--num_lines;num_lines>=0;--num_lines)
  296.         free(phrase[num_lines]);
  297. #endif
  298.  
  299.     return(next!=MY_EOF);
  300.     }
  301.  
  302. void
  303. main(argc,argv)
  304.     int argc;        /* Both arguments are unused in this example */
  305.     char **argv;
  306.    {/* Pick a single saying from a file and send it to the user */
  307.     FILE *fptr;        /* The data file */
  308.     long length;    /* The total length of the data file */
  309.     long where;        /* Where we are going to look for our phrase */
  310.  
  311.     /* Check the arguments */
  312.     if(argc>1)
  313.        {int i;
  314.  
  315.         for(i=1;i<argc;++i)
  316.            {if(0==stricmp(argv[i],"noisy"))
  317.                 noisy = 1;
  318.               else if(0==stricmp(argv[i],"silent"))
  319.                 silent = 1;
  320.             }
  321.         }
  322.         
  323.     /* First open the data file */
  324.     fptr = fopen(SRC_FILE,"r");
  325.  
  326.     /* Check to make sure that we got it */
  327.     if(fptr==NULL)
  328.        {printf("Remember:\n\n    A good user always keeps\n");
  329.         printf("    \"%s\" with his fortune program\n",SRC_FILE);
  330.         exit(20);
  331.         }
  332.  
  333.     /* 
  334.       Seed the random number generator, use the current time as a 
  335.     good source of random numbers 
  336.     */
  337.     srand(time(NULL));
  338.  
  339.     /* Find out how long the file is, first move to the end */
  340.     fseek(fptr,0L,SEEK_END);
  341.     /* Then ask where we now are */
  342.     length = ftell(fptr);
  343.  
  344.     /* 
  345.       Check that the file is long enough, this is not really 
  346.     required but we might get problems with small files
  347.     */
  348.     if(length<MIN_LENGTH)
  349.        {printf("Remember:\n\n    A good user makes sure \"%s\"\n",SRC_FILE);
  350.         printf("    is longer than %d charcters.\n",MIN_LENGTH);
  351.         exit(20);
  352.         }
  353.  
  354.     /* Output a wrapper to put round the phrase */
  355.     printf("Remember:\n\n    ");
  356.  
  357.     /* Now go look for a phrase in the file */
  358.     do {
  359.         /* Select somewhere in the middle of the file */
  360.         where = rand() % length;
  361.  
  362.         /* Move there */
  363.         fseek(fptr,where,SEEK_SET);
  364.  
  365.         /* 
  366.           Now move to the end of the prase we were in the middle of,
  367.         then output the next phrase.  If either function returns
  368.         false then we hit the end of the data file and must go round
  369.         and try again another place in the file.
  370.         */
  371.         } while (!find_next(fptr) || !out_next(fptr));
  372.  
  373.     /* Round the phrase off with a couple of newlines */
  374.     puts("\n\n");
  375.  
  376. #ifdef NORTHC
  377.  
  378.     if(_fromWB)
  379.        {/* Wait for the user to hit a key before quitting the program */
  380.         printf("Hit <Return>:");
  381.         /* OK make sure that the last bit gets sent for buffered stdout */
  382.         fflush(stdout);
  383.         fgetc(stdin);
  384.         }
  385.  
  386. #endif
  387.  
  388.     /* Close the data file */
  389.     fclose(fptr);
  390.     }
  391.